﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Ganaye.EmbeddedDb
{
    internal class TableClusteredFile : ClusteredFile, IHasEncoding
    {
        protected byte END_OF_COLUMN_DEFINITIONS = 13;
        internal TableDefinition mTableDefinition;
        internal Table.NewRecordFunction mNewRecordFunction;
        //internal DbfHeader mDbfHeader;
        private Encoding mEncoding;

        public TableClusteredFile()
        {
            mEncoding = System.Text.Encoding.UTF8;
            mTableDefinition = new TableDefinition();
        }

        protected override Record CreateNewProxyRecord()
        {
            return mNewRecordFunction();
        }


        protected override void OnInitializeNewFile()
        {
            
            //throw new NotImplementedException();
        }

        protected override void OnReadHeader()
        {
            //mDbfHeader = new DbfHeader();
            byte[] headerBytes = new byte[mTableDefinition.SerializationBufferSize()];
            mStream.Position = 0;
            mStream.Read(headerBytes, 0, headerBytes.Length);
            SimpleSerializer.SerializeFromBytes(this, headerBytes, mTableDefinition);

            if (mTableDefinition.RecordWidth == 0 || mTableDefinition.HeaderWidth == 0)
            {
                // our header is junk
                return;
            }
            //File size reported by the operating system must match the logical file size. Logical file size = ( Length of header + ( Number of modifiedRecords * Length of each record ) ) 
            var nbColumns = ((mTableDefinition.HeaderWidth - 32) / 32) + 1;
            Int64 totalLength = mStream.Length;
            //    var columns = new List<ColumnDefinition>(nbColumns);
            Int64 recordsLength = totalLength - mTableDefinition.HeaderWidth;
            UInt32 recordCount = (UInt32)(recordsLength / mTableDefinition.RecordWidth);

            ColumnDefinition column = new ColumnDefinition();
            Byte[] columnHeaderBytes = new byte[column.SerializationBufferSize()];
            List<ColumnDefinition> columns = new List<ColumnDefinition>();
            for (int i = 1; i < nbColumns; i++)
            {
                mStream.Read(columnHeaderBytes, 0, columnHeaderBytes.Length);
                SimpleSerializer.SerializeFromBytes(this, columnHeaderBytes, column);


                mTableDefinition.Columns.Add(
                    new ColumnDefinition(column.ColumnName,
                        (ColumnType)column.ColumnType)
                    {
                        Size = column.Size,
                        Decimals = column.Decimals
                    });
            }
            int lastByte = mStream.ReadByte();
            if (lastByte == END_OF_COLUMN_DEFINITIONS)
            {
                base.Initialize(mTableDefinition.HeaderWidth, mTableDefinition.RecordWidth);
            }
        }


        #region IHasEncoding Members

        Encoding IHasEncoding.Encoding
        {
            get
            {
                return mEncoding;
            }
        }

        char IHasEncoding.DecimalPoint
        {
            get { throw new NotImplementedException(); }
        }

        #endregion



        internal void WriteHeader(bool firstBit, byte[] buff)
        {
            if (firstBit) mStream.Seek(0, System.IO.SeekOrigin.Begin);
            mStream.Write(buff, 0, buff.Length);
        }
    }
}
